﻿<ComClass(ClsTools.ClassId, ClsTools.InterfaceId, ClsTools.EventsId)> _
Public Class ClsTools

#Region "COM GUID"
    ' 这些 GUID 提供此类的 COM 标识 
    ' 及其 COM 接口。若更改它们，则现有的
    ' 客户端将不再能访问此类。
    Public Const ClassId As String = "731923f1-6543-42ec-9ffb-dc6539afac26"
    Public Const InterfaceId As String = "622c93b3-581c-475a-a4e6-ee8742dc2856"
    Public Const EventsId As String = "3464e0ec-4cee-461b-aa84-777a30ef1768"
#End Region

    ' 可创建的 COM 类必须具有一个不带参数的 Public Sub New() 
    ' 否则， 将不会在 
    ' COM 注册表中注册此类，且无法通过
    ' CreateObject 创建此类。
    Public Sub New()
        MyBase.New()
    End Sub

    '@二维点或者二维向量
    Public Function C2P(Optional ByVal X As Double = 0, Optional ByVal Y As Double = 0) As Double()
        Dim p(1) As Double
        p(0) = X : p(1) = Y
        C2P = p
    End Function
    '二维点+二维向量构成新的点 或者向量
    Public Function P2AddVector(oriPt As Object, Vector2d As Object) As Double()
        Dim p(1) As Double
        p(0) = oriPt(0) + Vector2d(0) : p(1) = oriPt(1) + Vector2d(1)
        P2AddVector = p
    End Function
    '2维点坐标值的修改
    Public Function P2AddVal(oriPt As Object, Optional ByVal X As Double = 0, Optional ByVal Y As Double = 0) As Double()
        Dim p(1) As Double
        p(0) = oriPt(0) + X : p(1) = oriPt(1) + Y
        P2AddVal = p
    End Function
    '极坐标求点
    Public Function P2PolarPt(oriPt As Object, distance As Double, angle As Double) As Double()
        Dim p(1) As Double
        p(0) = oriPt(0) + distance * Math.Cos(angle) : p(1) = oriPt(1) + distance * Math.Sin(angle)
        P2PolarPt = p
    End Function

    '旋转点
    '在平面坐标上，任意点P(x1,y1)，绕一个坐标点Q(x2,y2)旋转θ角度后,新的坐标设为(x, y)的计算公式：
    'x= (x1 - x2)*cos(θ) - (y1 - y2)*sin(θ) + x2 ;
    'y= (x1 - x2)*sin(θ) + (y1 - y2)*cos(θ) + y2 ;
    'resPnt2d.X = (Me.X - origin.X) * Cos(angle) - (Me.Y - origin.Y) * Sin(angle) + origin.X
    'resPnt2d.Y = (Me.X - origin.X) * Sin(angle) + (Me.Y - origin.Y) * Cos(angle) + origin.Y
    Public Function P2Rotation(originalpt As Object, RotatedangleCenterPt As Object, Rotatedangle As Double) As Double()
        Dim resPnt2d(1) As Double
        resPnt2d(0) = (originalpt(0) - RotatedangleCenterPt(0)) * Math.Cos(Rotatedangle) - (originalpt(1) - RotatedangleCenterPt(1)) * Math.Sin(Rotatedangle) + originalpt(0)
        resPnt2d(1) = (originalpt(0) - RotatedangleCenterPt(0)) * Math.Sin(Rotatedangle) + (originalpt(1) - RotatedangleCenterPt(1)) * Math.Cos(Rotatedangle) + originalpt(1)
        P2Rotation = resPnt2d
    End Function

    'precision,精度
    Public Function NumberIsEqual(a As Double, b As Double, Optional precision As Double = 0.00000001) As Boolean
        Debug.Assert(precision > 0)
        NumberIsEqual = Math.Abs(a - b) <= precision
    End Function
    '创建3维点数据结构,或者三维向量
    Public Function C3P(Optional ByVal X As Double = 0, Optional ByVal Y As Double = 0, Optional ByVal Z As Double = 0) As Double()
        Dim p(2) As Double
        p(0) = X : p(1) = Y : p(2) = Z
        C3P = p
    End Function
    '3维点增加向量以获取新的点
    Public Function P3AddVector(oriPt As Object, Vector3d As Object) As Double()
        Dim p(2) As Double
        p(0) = oriPt(0) + Vector3d(0) : p(1) = oriPt(1) + Vector3d(1) : p(2) = oriPt(2) + Vector3d(2)
        P3AddVector = p
    End Function
    '3维点坐标值的修改
    Public Function P3AddVal(ByVal oriPt As Object, Optional ByVal X As Double = 0, Optional ByVal Y As Double = 0, Optional ByVal Z As Double = 0) As Double()
        Dim p(2) As Double

        p(0) = oriPt(0) + X : p(1) = oriPt(1) + Y : p(2) = oriPt(2) + Z
        P3AddVal = p
    End Function
    '两点创建二维向量
    Public Function C2dVector(ByVal sp As Object, ByVal ep As Object) As Double()

        Dim p(1) As Double
        p(0) = ep(0) - sp(0) : p(1) = ep(1) - sp(1)
        C2dVector = p
    End Function
    Public Function CrossProduct2d(va As Object, vb As Object) As Double

        CrossProduct2d = va(0) * vb(1) - va(1) * vb(0)
    End Function

    'a = λb,则a∥b,向量法a(x1,y1) b(x2,y2),若x1y2 = y1x2,则a∥b
    Public Function Vctor2dIsParallel(va As Object, vb As Object) As Boolean

        Vctor2dIsParallel = Math.Abs(CrossProduct2d(va, vb)) < 0.00000001

    End Function
    '若a*b=x1x2+y1y2=0,则a⊥b
    Public Function Vctor2dIsPerpendicular(va As Object, vb As Object) As Boolean

        Vctor2dIsPerpendicular = Math.Abs(DotProduct2d(va, vb)) < 0.00000001
    End Function

    '若a*b=x1x2+y1y2+z1z2=0,则a⊥b
    Public Function Vctor3dIsPerpendicular(va As Object, vb As Object) As Boolean

        Vctor3dIsPerpendicular = Math.Abs(DotProduct3d(va, vb)) < 0.00000001
    End Function

    Public Function DotProduct3d(va As Object, vb As Object) As Double

        DotProduct3d = va(0) * vb(0) + va(1) * vb(1) + va(2) * vb(2)
    End Function

    '点乘，也叫数量积。结果是一个向量在另一个向量方向上投影长度，是一个标量
    Public Function DotProduct2d(va As Object, vb As Object) As Double

        DotProduct2d = va(0) * vb(0) + va(1) * vb(1)
    End Function

    Public Function C3dVector(sp As Object, ep As Object) As Double()
        Dim p(2) As Double
        p(0) = ep(0) - sp(0) : p(1) = ep(1) - sp(1) : p(2) = ep(2) - sp(2)
        C3dVector = p
    End Function

    Public Function DistanceBetweenPoint3d(p1() As Double, p2() As Double) As Double
        Dim detlaX As Double
        Dim detlaY As Double
        Dim detlaZ As Double
        detlaX = p1(0) - p2(0) : detlaY = p1(1) - p2(1) : detlaZ = p1(2) - p2(2)
        DistanceBetweenPoint3d = Math.Sqrt(detlaX * detlaX + detlaY * detlaY + detlaZ * detlaZ)
    End Function

    Public Function DistanceBetweenPoint2d(p1() As Double, p2() As Double) As Double
        Dim detlaX As Double
        Dim detlaY As Double
        detlaX = p1(0) - p2(0) : detlaY = p1(1) - p2(1)
        DistanceBetweenPoint2d = Math.Sqrt(detlaX * detlaX + detlaY * detlaY)
    End Function

    Public Function MidBetweenPoint2d(p1() As Double, p2() As Double) As Double()
        Dim mp(1) As Double
        mp(0) = 0.5 * p1(0) + 0.5 * p2(0) : mp(1) = 0.5 * p1(1) + 0.5 * p2(1)
        MidBetweenPoint2d = mp
    End Function

    Public Function MidBetweenPoint3d(p1() As Double, p2() As Double) As Double()
        Dim mp(2) As Double
        mp(0) = 0.5 * p1(0) + 0.5 * p2(0) : mp(1) = 0.5 * p1(1) + 0.5 * p2(1) : mp(2) = 0.5 * p1(2) + 0.5 * p2(2)
        MidBetweenPoint3d = mp
    End Function


    Public Function PolarPoint2d(p1() As Double, ang As Double, dis As Double) As Double()
        Dim ep(1) As Double
        ep(0) = p1(0) + dis * Math.Cos(ang) : ep(1) = p1(0) + dis * Math.Sin(ang)
        PolarPoint2d = ep
    End Function

    Public Function PI() As Double
        PI = 4 * Math.Atan(1.0#)
    End Function

    Public Function HalfPi() As Double
        HalfPi = 0.5 * PI()
    End Function
    Public Function ThreeHalfPI() As Double
        ThreeHalfPI = 1.5 * PI()
    End Function
    Public Function TwoPI() As Double
        TwoPI = 2 * PI()
    End Function

    Public Function Degree2Rad(deg As Double) As Double
        Degree2Rad = (deg * PI()) / 180.0#
    End Function

    Public Function Rad2Degree(rad As Double) As Double
        Rad2Degree = (180 * rad) / PI()
    End Function

    Public Function 三角形面积(a() As Double, b() As Double, c() As Double) As Double
        三角形面积 = Math.Abs((b(0) - a(0)) * (c(1) - a(1)) - (b(1) - a(1)) * (c(0) - a(0))) / 2.0#
    End Function

    Public Function MySqrt(a As Double, b As Double) As Double
        MySqrt = Math.Sqrt(a * a + b * b)
    End Function

End Class


